package com.sufjan.secret.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

public class DBConnectionPool {

    /**
     * count how many connections are in use
     */
    private int inUsed = 0;
    
    /**
     * the container used to store the free connections
     */
    private ArrayList<Connection> freeConnections = new ArrayList<Connection>();
    
    /**
     * db username
     */
    private String username;
    
    /**
     * db password
     */
    private String password;
    
    /**
     * db url
     */
    private String url;
    
    /**
     * the min connection number permitted
     */
    private int minConn;
    
    /**
     * the max connection number premitted
     */
    private int maxConn;
    
    /**
     * constructor
     * store the db params
     * create minConn connections
     * 
     * @param driver
     * @param username
     * @param password
     * @param url
     * @param minConn
     * @param maxConn
     */
    public DBConnectionPool(String username, String password, String url, 
            int minConn, int maxConn) {
        this.username = username;
        this.password = password;
        this.url = url;
        this.minConn = minConn;
        this.maxConn = maxConn;
        
        for(int i = 0; i < this.minConn; i++) {
            freeConnections.add(newConnection());
        }
    }
    
    /**
     * getConnection
     * 
     * @return a Connection got from pool
     */
    public synchronized Connection getConnection() {
        Connection conn = null;
        
        if(freeConnections.size() > 0) {
            conn = freeConnections.remove(0);
            if(conn == null) {
                conn = getConnection();
            }
        } else {
            conn = newConnection();
        }
        
        if(maxConn == 0 || maxConn < inUsed) {
            conn = null;
        }
        
        if(conn != null) {
            ++inUsed;
        }
        
        return conn;
    }
    
    /**
     * freeConnection
     * 
     * @param conn - the connection about to return to the connection pool
     */
    public synchronized void freeConnection(Connection conn) {
        freeConnections.add(conn);
        --inUsed;
    }
    
    /**
     * newConnection
     * 
     * @return the newly created connection
     */
    private Connection newConnection() {
        Connection conn = null;
        
        try {
            conn = DriverManager.getConnection(url, username, password);
        } catch(SQLException e) {
        }
        
        return conn;
    }
    
    /**
     * release the connection pool
     */
    public synchronized void release() {
        Iterator<Connection> allConns = freeConnections.iterator();
        while(allConns.hasNext()) {
            Connection conn = allConns.next();
            try {
                conn.close();
            } catch(SQLException e) {
            }
        }
        freeConnections.clear();
        inUsed = 0;
    }
  
}
